import { Dep } from './Dep'
export default function initState(vm) {
    let data = vm.$options.data
    // {}
    data = vm_data = typeof data === 'function' ? data.call(vm, vm) : data || {}

    const keys = Object.keys(data)

    let i = keys.length
    // 劫持所有的数据源
    while(i--) {
        // 代理 , 让操作数据源变成 this.xxx 而不是 this.data.xxx
        proxy(vm, '_data', keys[i]) 
    }

    // 让数据源变成响应式
    observe(data)
}

class Observe{
    constructor(value) {
        this.walk(value)
    }
    walk(data) {
        let keys = Object.keys(data)
        for(let i = 0; i < keys.length; i++) {
            // 参数 {name: xx, age: xx}, name||age, '蜗牛' || 18
            defineReactive(data, keys[i], data[keys[i]])
        }
    }
}

function defineReactive(data, key, value) {
    const dep = new Dep()
    Object.defineProperty(data, key, {
        get() {
            if(Dep.target) {
                // 如果Dep.target指向某个watcher，酒吧watcher收入到这个dep里面
                dep.depend()
            }
        },
        set(newVal) {
            if(newVal === value) return
            value = newVal
            observe(newVal) // 新值也是响应式
            // 让dep里面的数据也进行更新
            dep.notify()
        }
    })
}

function observe(data) {
    if(typeof data === 'object' !== null) {
        return new Observe(data)
    }
}

function proxy(vm, source, key) {
    Object.defineProperty(vm, key, {
        get() {
            return vm[source][key]
        },
        set(newVal) {
            return vm[source][key] = newVal
        }
    })
}